<?php
set_time_limit(0);

//$host = "192.168.1.100";
$host = "localhost";
$port = 8000;

$key = "serverkey";
$uid = "uid_2";
$nickname = "nick_test";
$arr_friends = array("uid_1", "uid_2", "uid_3", "uid_4", "uid_5", "uid_6", "uid_7", "uid_8", "uid_9", "uid_10");

if ($argc > 1)
	$uid = $argv[1];

$thread = 0;

echo "\n";

for($t = 0; $t < $thread; $t++)
{
	if (pcntl_fork() == 0)
	{
		$uid = "uid_" . ($t+1);
		$start = microtime(true);
		test2();
		echo "thread:$t time:" . (microtime(true) - $start) . "\n";
		exit;
	}

}

if ($thread == 0){
	for($i=0; $i < 1; $i++){
		echo $i . "\r";
		test2();
	}
}

function test2()
{
	global $host, $port, $key, $nickname,$uid, $arr_friends;

	$fp = fsockopen($host, $port, $errno, $errstr, 1);
	if (!$fp) {
		echo "$errstr ($errno)\n";
		exit;
	} else {
		stream_set_timeout($fp, 20000);
		$login_pack = s(100) . str($key) .str($uid) . str($nickname);

		$friend_pack = s(103) . i(count($arr_friends));
		foreach($arr_friends as $fuid){
			$friend_pack .= str($fuid);
		}
		
		$channel_pack = s(107) . str("chat_world");
		
		$message_type = 99;
		$message = "test message";
		$msg_pack = s(110) . i($message_type) . str("chat_world") . str($message);

		write_pack($fp, $login_pack , $friend_pack, $channel_pack, $msg_pack);

		$pack_len = 0;
		while($result = wait_pack($fp)){
			$pack_len++;

			print_r($result);
		}

		fclose($fp);
	}
}

function write_pack($fp, $str)
{
	$num=func_num_args(); 
	$list=func_get_args(); 

	$wstr = "";
	for($i = 1; $i < $num; $i++)
	{
		$pack_len = strlen($list[$i]);
		$wstr .= i($pack_len) . $list[$i];
	}
	if (@fwrite($fp, $wstr) === false){
		$errorcode = socket_last_error();
		$errormsg = socket_strerror($errorcode);
		exit("fwrite fail! code:$errorcode error:$errormsg\n");
	}
}
function wait_pack($fp)
{
	$data = @fread($fp, 4);
	if (strlen($data) == 0){
		$errorcode = socket_last_error();
		$errormsg = socket_strerror($errorcode);
		exit("fread is 0 closed code:$errorcode, error:$errormsg\n");
	}

	$len = current(unpack("i", $data));
	$type = current(unpack("s", fread($fp, 2)));
	echo $len . "::" . $type . "\n";
	$data = fread($fp, $len - 2);
	$ret = array();

	if ($type == 101){
		$ret['status'] = current(unpack("i", $data));
	}elseif($type == 5){
		$ret['errortype'] = current(unpack("i", $data));
	}elseif($type == 104){//len+type+friendLength+[friendid,friendid...friendid]
		$ret['online_friend_count'] = current(unpack("i", $data));
		$ret['online_friends'] = array();

		$pos = 4;
		for($i = 0; $i < $ret['online_friend_count']; $i++){
			$len = current(unpack("i", substr($data, $pos)));

			$ret['online_friends'][] = current(unpack("a*", substr($data, $pos+4, $len)));
			$pos += 4 + $len;
		}
	}elseif($type == 105){
		$len = current(unpack("i", $data));
		$ret['online_uid'] = current(unpack("a*", substr($data, 4)));
	}elseif($type == 106){
		$len = current(unpack("i", $data));
		$ret['offline_uid'] = current(unpack("a*", substr($data, 4)));
	}elseif($type == 108 || $type == 109){
		$len = current(unpack("i", $data));
		$ret['channel_name'] = current(unpack("a*", substr($data, 4)));
	}elseif($type == 112 || $type == 113){
		$ret['message_type'] = current(unpack("i", $data));
		$pos = 4;

		$len = current(unpack("i", substr($data, $pos)));
		$pos += 4;
		$ret['src_uid'] = current(unpack("a*", substr($data, $pos, $len)));
		$pos += $len;

		$len = current(unpack("i", substr($data, $pos)));
		$pos += 4;
		$ret['src_nick'] = current(unpack("a*", substr($data, $pos, $len)));
		$pos += $len;

		$len = current(unpack("i", substr($data, $pos)));
		$pos += 4;
		$ret['channel_name'] = current(unpack("a*", substr($data, $pos, $len)));
		$pos += $len;

		$len = current(unpack("i", substr($data, $pos)));
		$pos += 4;
		$ret['message'] = current(unpack("a*", substr($data, $pos, $len)));
	}else if ($type == 117){
		$len = current(unpack("i", substr($data, $pos)));
		$pos += 4;
		$ret['expire_time'] = current(unpack("a*", substr($data, $pos, $len)));
	}

	return array("len" => $len, "type" => $type,'ret' => $ret);
}

// 封装字符串
function str($str)
{
	if ($str == NULL)
		return "";
	else
		return pack("i",strlen($str)) .   $str;
}

// 封装int
function i($i)
{
	return pack("i", $i);
}

// 封装short
function s($s)
{
	return pack("s", $s);
}
